package com.azusa.xbiao.controller;

import com.azusa.xbiao.entity.Result;
import com.azusa.xbiao.entity.StatusCode;
import com.azusa.xbiao.entity.User;
import com.azusa.xbiao.service.UserService;
import com.azusa.xbiao.utils.IdWorker;
import com.fasterxml.jackson.databind.ObjectMapper;
import org.apache.http.client.methods.CloseableHttpResponse;
import org.apache.http.client.methods.HttpGet;
import org.apache.http.impl.client.CloseableHttpClient;
import org.apache.http.impl.client.HttpClients;
import org.apache.http.util.EntityUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.http.HttpEntity;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import javax.servlet.http.HttpSession;
import java.io.IOException;
import java.net.URLEncoder;
import java.nio.charset.Charset;
import java.util.*;
import java.util.concurrent.TimeUnit;

@RestController
@RequestMapping("wx")
public class WxLoginController {

    @Value("${wx.appId}")
    private String appId;

    @Value("${wx.redirect_uri}")
    private String redirect_uri;

    @Value("${wx.appSecret}")
    private String appSecret;

    @Autowired
    private HttpServletResponse response;

    @Autowired
    private HttpServletRequest request;

    @Autowired
    private UserService userService;

    @Autowired
    private HttpSession session;

    @Autowired
    private RedisTemplate redisTemplate;

    @Autowired
    private IdWorker idWorker;

    @RequestMapping("to_wxLogin")
    public void toWxLogin() throws IOException {
        String url = "https://open.weixin.qq.com/connect/qrconnect?response_type=code"
                + "&appId=" + appId
                + "&redirect_uri=" + URLEncoder.encode(redirect_uri)
                + "&scope=snsapi_login";
        response.sendRedirect(url);
    }

    /**
     * 用户确认授权之后的操作
     * @throws IOException
     */
    @RequestMapping("/wx_login")
    public void wx_login() throws IOException {
        // 用户扫码成功后携带过来的code
        String code = request.getParameter("code");
        String url = "https://api.weixin.qq.com/sns/oauth2/access_token?appid=" + appId +
                "&secret=" + appSecret +
                "&code=" + code +
                "&grant_type=authorization_code";
        // 获取AccessToken、openid等数据
        HashMap<String,Object> info = auth(url);
        System.out.println("info: " + info);
        url = "https://api.weixin.qq.com/sns/userinfo?access_token=" + info.get("access_token") +
                "&openid=" + info.get("openid");

        HashMap<String,Object>  userInfo = getUserInfo(url);
        System.out.println("userInfo: " + userInfo);

        // 根据微信的openid查询此用户原来有没有使用过微信登录

        User user = userService.findByWxOpenid(info.get("openid").toString());

        // 说明该用户是第一次使用微信登录
        if (user == null) {
            // 获取用户信息
            HashMap<String,Object> jsonObject = getUserInfo(url);
            user = new User();
            //用户id
            user.setId((int) idWorker.nextId());
            // 用户的头像
            user.setPic(jsonObject.get("headimgurl").toString());
            // 性别
            user.setGender(0);
            // 用户的昵称
            user.setRealName(jsonObject.get("nickname").toString());
            user.setPassword("123456");
            // 用户名
            user.setUsername(user.getRealName());
            //用户购物车id
            user.setcId(new Random().nextInt(65534));
            //用户简介
            user.setIntro("微信登录用户");
            user.setCountry("Chinese");
            // 注册时间为当前时间
            user.setWxOpenid(info.get("openid").toString());
            // 注册一个新的用户
            userService.save(user);
            user = userService.findByWxOpenid(info.get("openid").toString());
        }
        session.setAttribute("userId", user.getId());
        redisTemplate.opsForValue().set("loginUser:" + user.getId(), user, 7, TimeUnit.DAYS);

        response.sendRedirect("/wx_login_info.html");
    }

    @PostMapping("getWxLoginInfo")
    public Result getWxLoginInfo() throws IOException {
        Object userId = session.getAttribute("userId");
        Map<String,Object> returnMap = new HashMap<>();
        returnMap.put("loginUser", redisTemplate.opsForValue().get("loginUser:" + userId));
        returnMap.put("userId", userId);
        return new Result(StatusCode.SUCCESS, returnMap);
    }

    /**
     * 认证
     * 获取AccessToken、openid等数据
     * @param url
     * @return
     */
    private HashMap<String,Object> auth(String url) {
        try {
            // 创建一个http Client请求
            CloseableHttpClient client = HttpClients.createDefault();
            HttpGet httpGet = new HttpGet(url);
            CloseableHttpResponse response = client.execute(httpGet);
            org.apache.http.HttpEntity entity = response.getEntity();       // 获取响应数据(json)
            if (entity != null) {
                String result = EntityUtils.toString(entity, Charset.forName("UTF8"));
                return new ObjectMapper().readValue(result, HashMap.class);
            }
        } catch (IOException e) {
            e.printStackTrace();
        }
        return null;
    }

    /**
     * 请求微信对外提供的接口获取用户信息
     * @param url
     * @return
     */
    private HashMap<String,Object> getUserInfo(String url) {
        try {
            CloseableHttpClient client = HttpClients.createDefault();
            HttpGet httpGet = new HttpGet(url);
            CloseableHttpResponse response = client.execute(httpGet);
            org.apache.http.HttpEntity entity = response.getEntity();
            if (entity != null) {
                String result = EntityUtils.toString(entity,Charset.forName("UTF8"));
                ObjectMapper mapper = new ObjectMapper();
                return mapper.readValue(result, HashMap.class);
            }
        } catch (IOException e) {
            e.printStackTrace();
        }
        return null;
    }
}
